package com.cv.platform.service.message;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cv.framework.common.utils.object.BeanUtils;
import com.cv.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cv.framework.security.core.utils.SecurityFrameworkUtil;
import com.cv.infra.api.file.FileApi;
import com.cv.platform.controller.platform.message.vo.record.CvMessageRecentRespVO;
import com.cv.platform.controller.platform.message.vo.record.CvMessageRespVO;
import com.cv.platform.controller.platform.message.vo.record.CvMessageSaveReqVO;
import com.cv.platform.controller.platform.message.vo.unreadCount.CvMessageUnreadCountRespVO;
import com.cv.platform.controller.platform.message.vo.unreadCount.CvMessageUnreadCountSaveReqVO;
import com.cv.platform.dal.dataobject.message.CvMessageDO;
import com.cv.platform.dal.mapper.message.CvMessageMapper;
import com.cv.system.api.user.UserApi;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 私信业务层接口实现类
 *
 * @author Charles_XDXD
 */
@Service
public class CvMessageServiceImpl implements CvMessageService {

    @Resource
    private CvMessageMapper cvMessageMapper;

    @Resource
    private CvMessageUnreadCountService cvMessageUnreadCountService;

    @Resource
    private CvConversationService cvConversationService;

    @DubboReference
    private UserApi userApi;

    @DubboReference
    private FileApi fileApi;

    @Override
    public List<CvMessageRespVO> getMessageList(Long conversationId) {
        Long userId = SecurityFrameworkUtil.getLoginUserId();
        LambdaQueryWrapper<CvMessageDO> wrapper = new LambdaQueryWrapperX<CvMessageDO>()
                .eq(CvMessageDO::getConversationId, conversationId)
                .orderByAsc(CvMessageDO::getSendTime);

        List<CvMessageDO> messageList = cvMessageMapper.selectList(wrapper);
        return BeanUtils.toBean(messageList, CvMessageRespVO.class);
    }

    @Override
    public void saveMessage(CvMessageSaveReqVO reqVO) {
        CvMessageDO cvMessageDO = BeanUtils.toBean(reqVO, CvMessageDO.class);
        cvMessageMapper.insert(cvMessageDO);

        Long conversationId = cvMessageDO.getConversationId();

        CvMessageUnreadCountSaveReqVO saveReqVO = new CvMessageUnreadCountSaveReqVO()
                .setUserId(reqVO.getReceiverId())
                .setConversationId(conversationId);
        cvMessageUnreadCountService.increaseUnreadCount(saveReqVO);
    }

    @Override
    public List<CvMessageRecentRespVO> getRecentList() {
        List<Long> conversationIdList = cvConversationService.getConversationIdList();
        if (CollUtil.isEmpty(conversationIdList)) {
            return Collections.emptyList();
        }

        List<CvMessageRecentRespVO> cvMessageRecentRespVOList = new ArrayList<>();
        for (Long conversationId : conversationIdList) {
            LambdaQueryWrapperX<CvMessageDO> wrapper = new LambdaQueryWrapperX<CvMessageDO>()
                    .eq(CvMessageDO::getConversationId, conversationId)
                    .orderByDesc(CvMessageDO::getSendTime)
                    .last("limit 1");
            CvMessageDO cvMessageDO = cvMessageMapper.selectOne(wrapper);
            if (ObjUtil.isNotEmpty(cvMessageDO)) {
                CvMessageRecentRespVO respVO = BeanUtils.toBean(cvMessageDO, CvMessageRecentRespVO.class);
                respVO.setUserId(cvMessageDO.getSenderId().equals(SecurityFrameworkUtil.getLoginUserId())
                        ? cvMessageDO.getReceiverId() : cvMessageDO.getSenderId());
                respVO.setNickname(userApi.getNicknameById(respVO.getUserId()));
                respVO.setAvatar(userApi.getAvatarById(respVO.getUserId()));
                respVO.setAvatarUrl(fileApi.getUrl(respVO.getAvatar()));
                cvMessageRecentRespVOList.add(respVO);
            } else {
                Long userId = cvConversationService.getTargetUserId(conversationId);
                if (ObjUtil.isNotEmpty(userId)) {
                    CvMessageRecentRespVO respVO = new CvMessageRecentRespVO()
                            .setConversationId(conversationId)
                            .setContent(StrUtil.EMPTY);
                    respVO.setUserId(userId);
                    respVO.setNickname(userApi.getNicknameById(userId));
                    respVO.setAvatar(userApi.getAvatarById(userId));
                    respVO.setAvatarUrl(fileApi.getUrl(respVO.getAvatar()));
                    cvMessageRecentRespVOList.add(respVO);
                }
            }
        }

        if (CollUtil.isEmpty(cvMessageRecentRespVOList)) {
            return Collections.emptyList();
        }

        // 可能存在 sendTime 为 null，如果为 null 则放到最前
        cvMessageRecentRespVOList.sort((o1, o2) -> {
            if (ObjUtil.isNotEmpty(o1.getSendTime()) && ObjUtil.isNotEmpty(o2.getSendTime())) {
                return o2.getSendTime().compareTo(o1.getSendTime());
            }
            if (ObjUtil.isNotEmpty(o1.getSendTime())) {
                return -1;
            }
            if (ObjUtil.isNotEmpty(o2.getSendTime())) {
                return 1;
            }
            return 0;
        });

        List<CvMessageUnreadCountRespVO> unreadCountList = cvMessageUnreadCountService.getUnreadCountList();
        for (CvMessageRecentRespVO cvMessageRecentRespVO : cvMessageRecentRespVOList) {
            for (CvMessageUnreadCountRespVO unreadCount : unreadCountList) {
                if (cvMessageRecentRespVO.getConversationId().equals(unreadCount.getConversationId())) {
                    cvMessageRecentRespVO.setUnreadCount(unreadCount.getUnreadCount());
                    break;
                }
            }
        }
        return cvMessageRecentRespVOList;
    }

    @Override
    public void setRead(Long conversationId) {
        LambdaUpdateWrapper<CvMessageDO> wrapper = new LambdaUpdateWrapper<CvMessageDO>()
                .eq(CvMessageDO::getConversationId, conversationId)
                .set(CvMessageDO::getIsRead, 1);
        cvMessageMapper.update(wrapper);
    }

    @Override
    public void deleteAllMessage(Long userId) {
        cvMessageMapper.delete(new LambdaQueryWrapperX<CvMessageDO>()
                .eq(CvMessageDO::getSenderId, userId)
                .or()
                .eq(CvMessageDO::getReceiverId, userId));
    }

}
